package com.cooper.scraper;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.content.res.Resources.NotFoundException;

public class RegExp {

	private Scraper scraper;

	public RegExp(Scraper scraper, XmlPullParser xml) {
		this.scraper = scraper;
		input = xml.getAttributeValue(null, "input");
		output = xml.getAttributeValue(null, "output");
		String destStr = xml.getAttributeValue(null, "dest");
		if (destStr.trim().charAt(destStr.length() - 1) == '+') {
			addDest = true;
			destStr = destStr.trim().substring(0, destStr.length() - 1);
		}
		dest = Integer.parseInt(destStr);
		conditional = xml.getAttributeValue(null, "conditional");
	}

	public String input;
	public String output;
	public Integer dest;
	public boolean addDest = false;
	public String conditional;
	public Exp exp;

	private RegExp parentRegExp;
	private List<RegExp> subRegExps = new ArrayList<RegExp>();

	public RegExp getParentRegExp() {
		return parentRegExp;
	}

	public List<RegExp> getSubRegExps() {
		return subRegExps;
	}

	public RegExp addSubRegExp(RegExp subRegExp) {
		subRegExps.add(subRegExp);
		subRegExp.parentRegExp = this;
		return subRegExp;
	}

	public void matchExp() throws DownloadException, XmlPullParserException,
			IOException {
		for (RegExp regExp : subRegExps) {
			regExp.matchExp();
		}
		String outResult = exp.matchExp(replaceBufferValue(input),
				replaceBufferValue(output));
		if (outResult == null || outResult.equals("")) {
			if (exp.clear) {
				scraper.getBuffer()[dest] = "";
			}
		} else {
			outResult = matchSubFuncTag(outResult);
			if (addDest) {
				scraper.getBuffer()[dest] += outResult;
			} else {
				scraper.getBuffer()[dest] = outResult;
			}
		}

	}

	private String matchSubFuncTag(String outResult) throws DownloadException,
			XmlPullParserException, IOException {

		Pattern p = Pattern
				.compile("<url[^>]*?function=\"(\\w+)\"[^>]*>([^<]+)</url>");
		Matcher m = p.matcher(outResult);
		StringBuffer result = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(result,
					matchSubFuncTag(ResultUrl.urlFactory(m.group(), null)
							.get(0)));
		}
		m.appendTail(result);
		return result.toString();
	}

	private String matchSubFuncTag(ResultUrl url) throws DownloadException,
			NotFoundException, XmlPullParserException, IOException {
		Scraper subFuncScraper = scraper.clonScraper();
		subFuncScraper.setBufferValue(1,
				scraper.getHttpDownload().downloadPage(url.getUrl(), url.getEncodingType()));
		return subFuncScraper.getDefineTag(url.getFunction()).matchRegExp();
	}


	private String replaceBufferValue(String str) {
		// replace param
		Pattern p = Pattern.compile("\\$INFO\\[(\\w+?)\\]");
		Matcher m = p.matcher(str);
		StringBuffer result = new StringBuffer();
		while (m.find()) {
			// if str have $ throw index out bound !!
			m.appendReplacement(result, scraper.getParams().get(m.group(1))
					.replace("$", ""));
		}
		m.appendTail(result);
		str = result.toString();

		// replace buffer
		String reg = "\\$\\$(\\d+)";
		p = Pattern.compile(reg);
		if (str.matches("^" + reg + "$")) {
			return scraper.getBuffer()[Integer.parseInt(str.substring(2))];
		}
		m = p.matcher(str);
		result = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(result, scraper.getBuffer()[Integer.parseInt(m
					.group(1))].replace("$", ""));
		}
		m.appendTail(result);

		return result.toString();
	}

}
